/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.form;
import java.awt.*;
import java.beans.*;
import java.text.MessageFormat;
import org.openide.TopManager;
import org.openide.explorer.propertysheet.editors.XMLPropertyEditor;
/**
* RADConnectionPropertyEditor is a property editor for ListModel, which
* encapsulates a connection to existing ListModel beans on the form
*
* @author Ian Formanek
*/
public class RADConnectionPropertyEditor
implements PropertyEditor,
FormAwareEditor,
XMLPropertyEditor,
NamedPropertyEditor
{
protected PropertyChangeSupport support;
private Class propertyType;
private RADComponent rcomponent;
private RADConnectionDesignValue emptyValue = null;
private RADConnectionDesignValue currentValue = emptyValue;
/** Creates a new RADConnectionPropertyEditor */
public RADConnectionPropertyEditor (Class propertyType) {
support = new PropertyChangeSupport (this);
this.propertyType = propertyType;
}
/** If a property editor or customizer implements the FormAwareEditor
* interface, this method is called immediately after the PropertyEditor
* instance is created or the Customizer is obtained from getCustomizer ().
* @param component The RADComponent representing the JavaBean being edited by this
* property editor or customizer
* @param property The RADProperty being edited by this property editor or null
* if this interface is implemented by a customizer
*/
public void setRADComponent (RADComponent rcomp, RADComponent.RADProperty rprop) {
rcomponent = rcomp;
}
// -----------------------------------------------------------------------------
// PropertyEditor implementation
public Object getValue () {
return currentValue;
}
public void setValue (Object value) {
if (value instanceof RADConnectionDesignValue) {
currentValue = (RADConnectionDesignValue)value;
} else {
currentValue = emptyValue;
}
support.firePropertyChange ("", null, null); // NOI18N
}
public void setAsText (String string) {
}
public String getAsText () {
if (currentValue != null)
return currentValue.getName ();
else return FormEditor.getFormBundle ().getString ("CTL_CONNECTION_NOT_SET"); //"<Not Set>";
}
public String[] getTags () {
return null;
}
public boolean isPaintable () {
return false;
}
public void paintValue (Graphics g, Rectangle rectangle) {
}
public boolean supportsCustomEditor () {
return true;
}
public java.awt.Component getCustomEditor () {
ParametersPicker pp = new ParametersPicker (rcomponent.getFormManager (), rcomponent, propertyType);
pp.setPropertyValue (currentValue);
return pp;
}
public String getJavaInitializationString () {
if (currentValue != null) {
switch (currentValue.type) {
case RADConnectionDesignValue.TYPE_VALUE:
if ("java.lang.String".equals (currentValue.requiredTypeName)) return "\""+currentValue.value+"\""; // NOI18N
else if ("long".equals (currentValue.requiredTypeName)) return currentValue.value+"L"; // NOI18N
else if ("float".equals (currentValue.requiredTypeName)) return currentValue.value+"F"; // NOI18N
else if ("double".equals (currentValue.requiredTypeName)) return currentValue.value+"D"; // NOI18N
else return currentValue.value;
case RADConnectionDesignValue.TYPE_CODE: return currentValue.userCode;
case RADConnectionDesignValue.TYPE_PROPERTY:
PropertyDescriptor pd = currentValue.getProperty ();
if (pd == null) return null; // failed to initialize => do not generate code
else {
if (currentValue.radComponent instanceof RADFormContainer) {
return pd.getReadMethod ().getName () + " ()"; // [FUTURE: Handle indexed properties] // NOI18N
} else {
return currentValue.radComponentName + "." + pd.getReadMethod ().getName () + " ()"; // [FUTURE: Handle indexed properties] // NOI18N
}
}
case RADConnectionDesignValue.TYPE_METHOD:
if (currentValue.radComponent instanceof RADFormContainer) {
return currentValue.methodName + " ()"; // NOI18N
} else {
return currentValue.radComponentName + "." + currentValue.methodName + " ()"; // NOI18N
}
case RADConnectionDesignValue.TYPE_BEAN:
if (currentValue.radComponent instanceof RADFormContainer) {
return "this"; // NOI18N
} else {
return currentValue.radComponentName;
}
}
}
return null;
}
public void addPropertyChangeListener (PropertyChangeListener propertyChangeListener) {
support.addPropertyChangeListener (propertyChangeListener);
}
public void removePropertyChangeListener (PropertyChangeListener propertyChangeListener) {
support.removePropertyChangeListener (propertyChangeListener);
}
// ------------------------------------------
// NamedPropertyEditor implementation
/** @return display name of the property editor */
public String getDisplayName() {
return FormEditor.getFormBundle ().getString ("CTL_RADConn_DisplayName");
}
public static class RADConnectionDesignValue implements FormDesignValue, java.io.Serializable {
public final static int TYPE_PROPERTY = 0;
public final static int TYPE_METHOD = 1;
public final static int TYPE_CODE = 2;
public final static int TYPE_VALUE = 3;
public final static int TYPE_BEAN = 4;
/** Determines the type of connection design value */
int type;
private transient RADComponent radComponent = null; // used if type = TYPE_PROPERTY or TYPE_METHOD or TYPE_BEAN
String radComponentName = null; // used if type = TYPE_PROPERTY or TYPE_METHOD
private transient MethodDescriptor method = null; // used if type = TYPE_METHOD
String methodName = null; // used if type = TYPE_METHOD
private transient PropertyDescriptor property = null; // used if type = TYPE_PROPERTY
String propertyName = null; // used if type = TYPE_PROPERTY
String userCode = null; // used if type = TYPE_CODE
String value = null; // used if type = TYPE_VALUE
String requiredTypeName = null; // used if type = TYPE_VALUE
transient private boolean needsInit = false; // used for deserialization init if type = TYPE_PROPERTY or TYPE_METHOD or TYPE_BEAN
transient private FormManager2 formManager; // used for deserialization init if type = TYPE_PROPERTY or TYPE_METHOD or TYPE_BEAN
static final long serialVersionUID =147134837271021412L;
RADConnectionDesignValue (RADComponent comp) {
radComponent = comp;
radComponentName = radComponent.getName ();
type = TYPE_BEAN;
}
RADConnectionDesignValue (RADComponent comp, MethodDescriptor md) {
radComponent = comp;
radComponentName = radComponent.getName ();
method = md;
methodName = md.getName ();
type = TYPE_METHOD;
}
RADConnectionDesignValue (RADComponent comp, PropertyDescriptor pd) {
radComponent = comp;
radComponentName = radComponent.getName ();
property = pd;
propertyName = pd.getName ();
type = TYPE_PROPERTY;
}
private RADConnectionDesignValue (String compName, int valueType, String name, FormManager2 manager) {
radComponentName = compName;
formManager = manager;
if (valueType == TYPE_PROPERTY) {
needsInit = true;
type = TYPE_PROPERTY;
propertyName = name;
} else if (valueType == TYPE_METHOD) {
needsInit = true;
type = TYPE_METHOD;
methodName = name;
} else if (valueType == TYPE_BEAN) {
needsInit = true;
type = TYPE_BEAN;
} else throw new IllegalArgumentException ();
}
RADConnectionDesignValue (Class requiredType, String valueText) {
this.requiredTypeName = requiredType.getName ();
this.value = valueText;
type = TYPE_VALUE;
}
RADConnectionDesignValue (String userCode) {
this.userCode = userCode;
type = TYPE_CODE;
}
String getName () {
switch (type) {
case TYPE_PROPERTY: return MessageFormat.format (FormEditor.getFormBundle ().getString ("FMT_PROPERTY_CONN"), new Object[] { radComponentName, propertyName });
case TYPE_METHOD: return MessageFormat.format (FormEditor.getFormBundle ().getString ("FMT_METHOD_CONN"), new Object[] { radComponentName, methodName });
case TYPE_VALUE: return MessageFormat.format (FormEditor.getFormBundle ().getString ("FMT_VALUE_CONN"), new Object[] { value });
case TYPE_CODE: return FormEditor.getFormBundle ().getString ("CTL_CODE_CONN");
case TYPE_BEAN: return MessageFormat.format (FormEditor.getFormBundle ().getString ("FMT_BEAN_CONN"), new Object[] { radComponentName });
}
throw new InternalError ();
}
PropertyDescriptor getProperty () {
if (needsInit) {
if (!initialize ()) return null;
}
return property;
}
MethodDescriptor getMethod () {
if (needsInit) {
if (!initialize ()) return null;
}
return method;
}
RADComponent getRADComponent () {
if (needsInit) {
if (!initialize ()) return null;
}
return radComponent;
}
private boolean initialize () {
radComponent = formManager.findRADComponent (radComponentName);
if (radComponent != null) {
if (type == TYPE_BEAN) { // bean
return true;
} else if (type == TYPE_PROPERTY) { // property
PropertyDescriptor[] componentsProps = radComponent.getBeanInfo ().getPropertyDescriptors ();
for (int i = 0; i < componentsProps.length; i++) {
if (componentsProps[i].getName ().equals (propertyName)) {
property = componentsProps[i];
return true;
}
} // if the property of given name cannot be found => ignore
} else { // method
MethodDescriptor[] componentMethods = radComponent.getBeanInfo ().getMethodDescriptors ();
for (int i = 0; i < componentMethods.length; i++) {
if (componentMethods[i].getName ().equals (methodName)) {
method = componentMethods[i];
return true;
}
} // if the property of given name cannot be found => ignore
}
} // if the component cannot be found, simply ignore it
return false;
}
/** Provides a value which should be used during design-time
* as the real property value on the bean instance.
* E.g. the ResourceBundle String would provide the real value
* of the String from the resource bundle, so that the design-time
* representation reflects the real code being generated.
* @param radComponent the radComponent in which this property is used
* @return the real property value to be used during design-time
*/
public Object getDesignValue (RADComponent radComponent) {
/* if (needsInit) {
if (!initialize ()) {
return IGNORED_VALUE; // failed to initialize
}
} */
switch (type) {
case TYPE_PROPERTY:
return FormDesignValue.IGNORED_VALUE; // [PENDING: use the value during design time]
/* try {
Object value = property.getReadMethod ().invoke (radComponent.getBeanInstance (), new Object[0]);
return value;
} catch (Exception e) {
// in case of failure do not provide the value during design time
return FormDesignValue.IGNORED_VALUE;
}*/ // [PENDING]
case TYPE_METHOD:
return FormDesignValue.IGNORED_VALUE; // [PENDING: use the value during design time]
/* try {
Object value = method.getMethod ().invoke (radComponent.getBeanInstance (), new Object[0]);
return value;
} catch (Exception e) {
// in case of failure do not provide the value during design time
return FormDesignValue.IGNORED_VALUE;
} */ // [PENDING]
case TYPE_VALUE:
return parseValue (requiredTypeName, value);
case TYPE_BEAN:
return FormDesignValue.IGNORED_VALUE; // [PENDING: use the value during design time]
case TYPE_CODE:
default:
return FormDesignValue.IGNORED_VALUE;
}
}
}
private static Object parseValue (String typeName, String value) {
try {
if ("java.lang.String".equals (typeName)) { // NOI18N
return value;
} else if ("int".equals (typeName)) { // NOI18N
return Integer.valueOf (value);
} else if ("short".equals (typeName)) { // NOI18N
return Short.valueOf (value);
} else if ("long".equals (typeName)) { // NOI18N
return Long.valueOf (value);
} else if ("byte".equals (typeName)) { // NOI18N
return Byte.valueOf (value);
} else if ("float".equals (typeName)) { // NOI18N
return Float.valueOf (value);
} else if ("double".equals (typeName)) { // NOI18N
return Double.valueOf (value);
} else if ("boolean".equals (typeName)) { // NOI18N
return Boolean.valueOf (value);
} else if ("char".equals (typeName)) { // NOI18N
if (value.length () > 0) return new Character (value.charAt (0));
}
return FormDesignValue.IGNORED_VALUE;
} catch (Exception e) {
// some problem => use ignored value
return FormDesignValue.IGNORED_VALUE;
}
}
//--------------------------------------------------------------------------
// XMLPropertyEditor implementation
public static final String XML_CONNECTION = "Connection"; // NOI18N
public static final String ATTR_TYPE = "type"; // NOI18N
public static final String ATTR_COMPONENT = "component"; // NOI18N
public static final String ATTR_NAME = "name"; // NOI18N
public static final String ATTR_CODE = "code"; // NOI18N
public static final String ATTR_VALUE = "value"; // NOI18N
public static final String ATTR_REQUIRED_TYPE = "valueType"; // NOI18N
public static final String VALUE_VALUE = "value"; // NOI18N
public static final String VALUE_PROPERTY = "property"; // NOI18N
public static final String VALUE_METHOD = "method"; // NOI18N
public static final String VALUE_BEAN = "bean"; // NOI18N
public static final String VALUE_CODE = "code"; // NOI18N
/** Called to load property value from specified XML subtree. If succesfully loaded,
* the value should be available via the getValue method.
* An IOException should be thrown when the value cannot be restored from the specified XML element
* @param element the XML DOM element representing a subtree of XML from which the value should be loaded
* @exception IOException thrown when the value cannot be restored from the specified XML element
*/
public void readFromXML (org.w3c.dom.Node element) throws java.io.IOException {
if (!XML_CONNECTION.equals (element.getNodeName ())) {
throw new java.io.IOException ();
}
org.w3c.dom.NamedNodeMap attributes = element.getAttributes ();
try {
String typeString = attributes.getNamedItem (ATTR_TYPE).getNodeValue ();
int type = RADConnectionDesignValue.TYPE_CODE;
if (VALUE_VALUE.equals (typeString)) {
String value = attributes.getNamedItem (ATTR_VALUE).getNodeValue ();
String valueType = attributes.getNamedItem (ATTR_REQUIRED_TYPE).getNodeValue ();
try {
Class reqType = TopManager.getDefault ().currentClassLoader ().loadClass (valueType);
setValue (new RADConnectionDesignValue (reqType, value));
} catch (Exception e) {
// ignore failures... and use no conn instead
}
} else if (VALUE_PROPERTY.equals (typeString)) {
String component = attributes.getNamedItem (ATTR_COMPONENT).getNodeValue ();
String name = attributes.getNamedItem (ATTR_NAME).getNodeValue ();
setValue (new RADConnectionDesignValue (component, RADConnectionDesignValue.TYPE_PROPERTY, name, rcomponent.getFormManager ()));
} else if (VALUE_METHOD.equals (typeString)) {
String component = attributes.getNamedItem (ATTR_COMPONENT).getNodeValue ();
String name = attributes.getNamedItem (ATTR_NAME).getNodeValue ();
setValue (new RADConnectionDesignValue (component, RADConnectionDesignValue.TYPE_METHOD, name, rcomponent.getFormManager ()));
} else if (VALUE_BEAN.equals (typeString)) {
String component = attributes.getNamedItem (ATTR_COMPONENT).getNodeValue ();
setValue (new RADConnectionDesignValue (component, RADConnectionDesignValue.TYPE_BEAN, null, rcomponent.getFormManager ()));
} else {
String code = attributes.getNamedItem (ATTR_CODE).getNodeValue();
setValue (new RADConnectionDesignValue (code));
}
} catch (NullPointerException e) {
if (System.getProperty ("netbeans.debug.exceptions") != null) {
e.printStackTrace ();
}
throw new java.io.IOException ();
}
}
/** Called to store current property value into XML subtree. The property
* value should be set using the setValue method prior to calling this method.
* @param doc The XML document to store the XML in - should be used for creating nodes only
* @return the XML DOM element representing a subtree of XML from which the
* value should be loaded
*/
public org.w3c.dom.Node storeToXML(org.w3c.dom.Document doc) {
org.w3c.dom.Element el = doc.createElement (XML_CONNECTION);
if (currentValue == null) return null;
String typeString;
switch (currentValue.type) {
case RADConnectionDesignValue.TYPE_VALUE: typeString = VALUE_VALUE; break;
case RADConnectionDesignValue.TYPE_PROPERTY: typeString = VALUE_PROPERTY; break;
case RADConnectionDesignValue.TYPE_METHOD: typeString = VALUE_METHOD; break;
case RADConnectionDesignValue.TYPE_BEAN: typeString = VALUE_BEAN; break;
case RADConnectionDesignValue.TYPE_CODE:
default:
typeString = VALUE_CODE; break;
}
el.setAttribute (ATTR_TYPE, typeString);
switch (currentValue.type) {
case RADConnectionDesignValue.TYPE_VALUE:
el.setAttribute (ATTR_VALUE, currentValue.value);
el.setAttribute (ATTR_REQUIRED_TYPE, currentValue.requiredTypeName);
break;
case RADConnectionDesignValue.TYPE_PROPERTY:
el.setAttribute (ATTR_COMPONENT, currentValue.radComponentName);
el.setAttribute (ATTR_NAME, currentValue.propertyName);
break;
case RADConnectionDesignValue.TYPE_METHOD:
el.setAttribute (ATTR_COMPONENT, currentValue.radComponentName);
el.setAttribute (ATTR_NAME, currentValue.methodName);
break;
case RADConnectionDesignValue.TYPE_BEAN:
el.setAttribute (ATTR_COMPONENT, currentValue.radComponentName);
break;
case RADConnectionDesignValue.TYPE_CODE:
el.setAttribute (ATTR_CODE, currentValue.userCode);
break;
}
return el;
}
}
/*
* Log
*/